﻿using CoachingOrganizer.Logic.Models.Common;
using CoachingOrganizer.Toolkit.Collections.Helpers;
using CoachingOrganizer.Toolkit.Events;
using CoachingOrganizer.WinPhone.UITools;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Input;
using Windows.UI.Popups;

namespace CoachingOrganizer.WinPhone.ViewModels
{
    public class PeriodViewModel : ViewModelBase
    {
        private readonly PeriodModel _model;
        private string _newGoalName;
        private ObservableCollection<GoalViewModel> _goals;

        public ObservableCollection<GoalViewModel> Goals
        {
            get { return _goals; }
        }

        public DateTime StartDate
        {
            get { return _model.StartDate; }
            set { _model.StartDate = value; }
        }

        public DateTime FinishDate
        {
            get { return _model.FinishDate; }
            set { _model.FinishDate = value; }
        }

        public string NewGoalName
        {
            get { return _newGoalName; }
            set
            {
                if (_newGoalName != value)
                {
                    _newGoalName = value;
                    OnCommandCanExecuteChanged(() => AddNewGoalCommand);
                }
            }
        }

        public ICommand GoDetailsCommand
        {
            get { return GetCommand(() => GoDetailsCommand, () => UIHelper.GoToPage(this, typeof(CoachingOrganizer.WinPhone.Pages.PeriodPage))); }
        }

        public ICommand SaveCommand
        {
            get { return GetCommand(() => SaveCommand, () => Save()); }
        }

        public ICommand RemoveCommand
        {
            get { return GetCommand(() => RemoveCommand, () => Remove()); }
        }

        public ICommand AddNewGoalCommand
        {
            get { return GetCommand(() => AddNewGoalCommand, () => AddNewGoal(), () => !string.IsNullOrWhiteSpace(_newGoalName)); }
        }

        public PeriodViewModel(PeriodModel model)
        {
            _model = model;
            _model.GoalsChanged += Model_GoalsChanged;
            _model.GoalsCollectionChanged += Model_GoalsCollectionChanged;
            InitModel();
        }

        private async void InitModel()
        {
            using (CancellationTokenSource cancellation = new CancellationTokenSource())
                await _model.LoadGoalsAsync(cancellation.Token);
        }

        private async void NotifyLoadFailed()
        {
            MessageDialog dialog = new MessageDialog("");
            await dialog.ShowAsync();
        }

        private async void AddNewGoal()
        {
            ActionResult result = await _model.AddNewGoal(_newGoalName);
            if (!result.IsValid)
                await UIHelper.ShowErrorMessageAsync("");
        }

        private async void Save()
        {
            ActionResult result = await _model.Save();
            if (!result.IsValid)
                await UIHelper.ShowErrorMessageAsync("");
        }

        private async void Remove()
        {
            ActionResult result = await _model.Remove();
            if (!result.IsValid)
                await UIHelper.ShowErrorMessageAsync("");
        }

        private void Model_GoalsChanged(object sender, EventArgs e)
        {
            IEnumerable<GoalModel> goals = _model.Goals;
            BeginInvokeInUIThread(() =>
            {
                _goals = goals == null ? null : new ObservableCollection<GoalViewModel>(goals.Select(m => new GoalViewModel(m)));
                OnPropertyChanged(() => Goals);
            });
        }

        private void Model_GoalsCollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            BeginInvokeInUIThread(() => ObservableCollectionHelper.ApplyChangesByNumbers<GoalModel, GoalViewModel>(e, _goals, m => new GoalViewModel(m)));
        }
    }
}
